package com.itstyle.seckill.common.encrypt;

import java.security.Key;
import java.security.NoSuchAlgorithmException;

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.spec.SecretKeySpec;

/**
 * 对称加密
 * 这里面的 API 里面有很多是调用 getInstance方法，这个方法的参数有 algorithm 或者 transformation
 * Java 加密解密官方参考文档：
 * https://docs.oracle.com/javase/8/docs/technotes/guides/security/index.html
 * https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html
 */
public class SecurityDES {
    /*
     * 使用 KeyGenerator 生成 key
     *
     * 其中，algorithm 支持的算法有：AES、DES、DESEDE、HMACMD5、HMACSHA1、HMACSHA256、RC2等
     * 全部支持的算法见官方文档
     * https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#KeyGenerator
     *
     */
    public static Key newKeyByKeyGenerator(String algorithm) throws NoSuchAlgorithmException {
        KeyGenerator kg = KeyGenerator.getInstance(algorithm);
        Key key = kg.generateKey();
        return key;
    }

    /**
     * 使用 SecretKeySpec 生成key
     * 一般是从一个文件中读取出 key 的 byte 数组，然后根据文件 key 的算法，构建出 key 对象
     */
    public static Key newKeyBySecretKeySpec(byte[] key, String algorithm) throws NoSuchAlgorithmException {
        return new SecretKeySpec(key, algorithm);
    }

    /**
     * 加密，对字符串进行加密，返回结果为 byte 数组
     * 保存的时候，可以把 byte 数组进行 base64 编码成字符串，或者把 byte 数组转换成 16 进制的字符串
     * 其中，transformation 支持的全部算法见官方文档：
     * https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#Cipher
     */
    public static byte[] encrypt(String transformation, Key key, String password) throws Exception {
        Cipher cipher = Cipher.getInstance(transformation);
        // 加密模式
        cipher.init(Cipher.ENCRYPT_MODE, key);
        return cipher.doFinal(password.getBytes());
    }

    /**
     * 解密，返回结果为原始字符串
     * 其中，transformation 支持的全部算法见官方文档：
     * https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#Cipher
     */
    public static String decrypt(String transformation, Key key, byte[] data) throws Exception {
        Cipher cipher = Cipher.getInstance(transformation);
        // 解密模式
        cipher.init(Cipher.DECRYPT_MODE, key);
        byte[] result = cipher.doFinal(data);
        String password = new String(result);
        return password;
    }

    public static void main(String[] args) throws Exception {
        String password = "123456";

        String algorithm = "DES";
        String transformation = algorithm;

        // 加密解密使用的都是同一个秘钥 key
        Key key = newKeyByKeyGenerator(algorithm);
        System.out.println(" 秘钥: " + key);
        // 加密
        byte[] passData = encrypt(transformation, key, password);
        // 解密
        String pass = decrypt(transformation, key, passData);

        System.out.println("解密后的密码 : " + pass);
    }
}
